#ifndef BENCODEPARSER_H_
#define BENCODEPARSER_H_

#include <string>
#include <sstream>
#include <iostream>
#include <list>
#include <map>
#include <stdlib.h>
#include <stdio.h>

class ElementoBencode;
class DiccionarioBencode;
class CadenaBencode;
class IntegerBencode;
class ListaBencode;

using namespace std;

/* Nota: Esta clase se encarga de parsear stringstreams que contengan un formato valido bencode,
 * lee el stream que se le pasa por argumento a la funcion getElemento y crea cada vez
 * el elemento correspondiente al stream.
 */

class BencodeParser {
public:

	/* Pre : -
	 * Pos: Crea una nueva instancia de BencodeParser.
	 */
	BencodeParser();

	/*
	 * Pos: Libera los recursos instanciados.
	 */
	virtual ~BencodeParser();

	/* Pre: El stream contenga una cadena valida segun el formato de Bendcode
	 * Pos: Devuelve un elemento Bencode y avanza sobre el stream para una proxima lectura,
	 * 		en caso de que el stream no sea valido o no contenga mas elementos devolvera NULL.
	 */

	ElementoBencode* getElemento(stringstream &stream);

	/* Pre: El elemento no sea nulo.
	 * Pos: Libera los recursos que fueron instanciados para la creacion del elemento.
	 */
	void borrarRecursosInstanciados(ElementoBencode* elemento);

	/* Pre: Se haya procesado un codigo Bencode con un diccionario que contenta la clave 'info'
	 * Pos: Devuelve el offset inicial del elemento de clave info.
	 */
	unsigned long long int getOffsetInicialTorrentInfo() const;

	/* Pre: Se haya procesado un codigo Bencode con un diccionario que contenta la clave 'info'
	 * Pos: Devuelve el offset final del elemento de clave info.
	 */

	unsigned long long int getOffsetFinalTorrentInfo() const;

private:

	/* Pre: El stream contenga un formato valido para crear un elemento diccionario.
	 * Pos: Retorna el elemento diccionario creado.
	 */
	ElementoBencode* crearDiccionario(stringstream &stream);

	/* Pre: El stream contenga un formato valido para crear un elemento cadena.
	 * Pos: Retorna el elemento cadena creado.
	 */

	ElementoBencode* crearCadena(stringstream &stream);

	/* Pre: El stream contenga un formato valido para crear un elemento Integer.
	 * Pos: Retorna el elemento Integer creado.
	 */

	ElementoBencode* crearInteger(stringstream &stream);

	/* Pre: El stream contenga un formato valido para crear un elemento Lista.
	 * Pos: Retorna el elemento lista creado.
	 */

	ElementoBencode* crearLista(stringstream &stream);


	/* Variable que se utiliza para obtener el offset inicial del diccionario de clave info en el archivo
	 * y luego se utiliza esta para calcular el hash del mismo*/

	unsigned long long int offsetInicialTorrentInfo;

	/* Variable que se utiliza para obtener el offset final del diccionario de clave info en el archivo
	 * y luego se utiliza esta para calcular el hash del mismo*/

	unsigned long long int offsetFinalTorrentInfo;
};

#endif /* BENCODEPARSER_H_ */
